package com.gitee.wsl.struct.command.model.parameters.options

interface OptionTransform<AllT, EachT, ValueT> {
    /** Called in [finalize] to transform each value provided to each invocation. */
    val transformValue: ValueTransformer<ValueT>

    /** Called in [finalize] to transform each invocation. */
    val transformEach: ValuesTransformer<ValueT, EachT>

    /** Called in [finalize] to transform all invocations into the final value. */
    val transformAll: AllTransformer<EachT, AllT>

    /** Called after all parameters have been [finalized][finalize] to validate the output of [transformAll] */
    val transformValidator: OptionValidator<AllT>
}


/** A callback that transforms a single value from a string to the value type */
typealias ValueTransformer<ValueT> = ValueConverter<String, ValueT>

/** A block that converts a single value from one type to another */
typealias ValueConverter<InT, ValueT> = OptionCallTransformContext.(InT) -> ValueT

/**
 * A callback that transforms all values for each call after the individual values have been converted.
 *
 * The input list will always have a size withing the range of `nvalues`
 */
typealias ValuesTransformer<ValueT, EachT> = OptionCallTransformContext.(List<ValueT>) -> EachT

/**
 * A callback that transforms all the calls to the final option type.
 *
 * The input list will have a size equal to the number of times the option appears on the command line.
 */
typealias AllTransformer<EachT, AllT> = OptionTransformContext.(List<EachT>) -> AllT

/** A callback validates the final option type */
typealias OptionValidator<AllT> = OptionTransformContext.(AllT) -> Unit


@PublishedApi
internal fun <T> defaultEachProcessor(): ValuesTransformer<T, T> = { it.single() }

@PublishedApi
internal fun <T> defaultAllProcessor(): AllTransformer<T, T?> = { it.lastOrNull() }

@PublishedApi
internal fun <T> defaultValidator(): OptionValidator<T> = { }